package cn.blu10ph.tools.web_ctrl;


import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import fi.iki.elonen.NanoHTTPD;
import fi.iki.elonen.NanoWSD;

public class WebSocketServer extends NanoWSD {
    private final boolean debug;
    private String password;

    public WebSocketServer() {
        super(19090);
        this.debug = false;
    }

    public WebSocketServer(int port,String password, boolean debug) {
        super(port);
        this.debug = debug;
        this.password = password;
    }

    @Override
    protected WebSocket openWebSocket(IHTTPSession handshake) {
        return new WebSocketImpl(this, handshake,password);
    }

    private static class WebSocketImpl extends WebSocket {
        /**
         * logger to log to.
         */
        private final Logger LOG = Logger.getLogger(WebSocketServer.class.getName());

        private final WebSocketServer server;
        private final NanoHTTPD.IHTTPSession handshakeRequest;
        private String password;
        protected CmdCtrl cmdCtrl;

        public WebSocketImpl(WebSocketServer server, IHTTPSession handshakeRequest,String password) {
            super(handshakeRequest);
            this.server = server;
            this.handshakeRequest = handshakeRequest;
            this.password = password;
            cmdCtrl = new CmdCtrl(this.password);
        }

        @Override
        protected void onOpen() {
            if (server.debug) {
                LOG.log(Level.INFO,"onOpen");
                try{
                    send("open");
                }catch (Exception ex){
                    LOG.log(Level.INFO,"onOpen_Exception"+ex.getMessage());
                }
            }
        }

        @Override
        protected void onClose(WebSocketFrame.CloseCode code, String reason, boolean initiatedByRemote) {
            if (server.debug) {
                LOG.log(Level.INFO,"onClose C [" + (initiatedByRemote ? "Remote" : "Self") + "] " + (code != null ? code : "UnknownCloseCode[" + code + "]")
                        + (reason != null && !"".equals(reason) ? ": " + reason : ""));
            }
            cmdCtrl = new CmdCtrl(this.password);
        }

        @Override
        protected void onMessage(WebSocketFrame message) {
            if (server.debug) {
                LOG.log(Level.INFO, "onMessage");
            }
            boolean is_close = false;
            try {
                message.setUnmasked();
                String msg = message.getTextPayload();
                is_close = cmdCtrl.cmd(msg);
                sendFrame(message);
                if(is_close){
                    close(WebSocketFrame.CloseCode.NormalClosure,"客户端连接已被关闭",true);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        protected void onPong(WebSocketFrame pong) {
            if (server.debug) {
                LOG.log(Level.INFO,"onPong");
            }
        }

        @Override
        protected void onException(IOException exception) {
            LOG.log(Level.INFO, "exception occured");
        }

        @Override
        protected void debugFrameReceived(WebSocketFrame frame) {
            if (server.debug) {
                LOG.log(Level.INFO,"debugFrameReceived");
            }
        }

        @Override
        protected void debugFrameSent(WebSocketFrame frame) {
            if (server.debug) {
                LOG.log(Level.INFO,"debugFrameSent");
            }
        }
    }
}